package com.xinbochuang.machine.admin.controller.macroom;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.supermap.data.*;
import com.supermap.data.conversion.*;
import com.xinbochuang.machine.admin.domain.macRoom.GeoCabinet;
import com.xinbochuang.machine.admin.domain.macRoom.GeoPoint;
import com.xinbochuang.machine.admin.domain.macRoom.Geometries;
import com.xinbochuang.machine.admin.service.macRoom.IEquCabinetService;
import com.xinbochuang.machine.common.controller.BaseController;
import com.xinbochuang.machine.common.utils.GeoUtils;
import com.xinbochuang.machine.framework.web.domain.AjaxResult;
import com.xinbochuang.machine.test.EquObj;
import com.xinbochuang.machine.test.Layers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author 黄晓鹏
 * @date 2020-11-19 15:06
 */
@RestController
@RequestMapping("/cad")
@Slf4j
public class CadParseController extends BaseController {

    /**
     * cad临时上传路径
     */
    @Value("${machine.temp-upload-path}")
    private String uploadPath;

    /**
     * superMap工作空间路径
     */
    @Value("${machine.superMap.workspace-path}")
    private String workspacePath;

    /**
     * 允许上传的文件类型
     */
    private final static String FILE_TYPE = "dwg";

    /**
     * cad图层中Feature特征Geometry几何图形为多边形的类型
     */
    private final static String GEOMETRY_TYPE = "GeometryCollection";

    /**
     * 机柜图层名称
     */
    @Value("${machine.superMap.cabinet-layer}")
    private String cabinetLayer;

    /**
     * 机柜图层名称
     */
    @Value("${machine.superMap.text-layer}")
    private String textLayer;

    @Resource
    private IEquCabinetService cabinetService;

    /**
     * cad解析导入机柜
     */
    @PreAuthorize("@ss.hasPermi('system:cad:import')")
    @PostMapping("/import")
    public AjaxResult add(@RequestParam("macId") String macId, @RequestParam("file") MultipartFile file) {
        //原文件名
        String fileName = file.getOriginalFilename();
        //文件后缀
        String extName = fileName.substring(fileName.lastIndexOf("."));
        if (!FILE_TYPE.equals(extName.substring(1))) {
            return AjaxResult.error("上传文件类型错误！");
        }
        //重命名文件
        String uploadName = DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + extName;
        //创建目录
        FileUtil.mkdir(uploadPath);
        try {
            //上传文件
            file.transferTo(new File(uploadPath, uploadName));
            //解析dwg
            Map<String, Object> map = parseDwg(uploadPath + "/" + uploadName);
            List<GeoCabinet> geoCabinetList = (List<GeoCabinet>) map.get("geoCabinetList");
            List<GeoPoint> pointList = (List<GeoPoint>) map.get("pointList");
            List<Map<Integer, EquObj>> equList = (List<Map<Integer, EquObj>>) map.get("equList");
            //判断文字坐标是否在机柜坐标中
            for (GeoCabinet geoCabinet : geoCabinetList) {
                geoCabinet.setMacId(macId);
                for (GeoPoint geoPoint : pointList) {
                    if (GeoUtils.isPtInPoly(geoPoint.getPoint(), geoCabinet.getPoints())) {
                        geoCabinet.setName(geoPoint.getName());
                        break;
                    }
                }
            }
            //添加中心点和角度
            for (GeoCabinet geoCabinet : geoCabinetList) {
                for (Map<Integer, EquObj> equObjMap : equList) {
                    for (Integer index : equObjMap.keySet()) {
                        EquObj equObj = equObjMap.get(index);
                        if (equObj.getEntityHandle() == geoCabinet.getEntityHandle()) {
                            Point2D.Double center = new Point2D.Double(equObj.getCenterPoint().getX(), equObj.getCenterPoint().getY());
                            geoCabinet.setCenter(center);
                            geoCabinet.setRadian(equObj.getAngle());
                        }
                    }
                }
            }
            return toAjax(cabinetService.cadAdd(geoCabinetList));
        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 解析dwg
     *
     * @param filePath dwg文件路径
     * @return 机柜坐标集合与文字坐标集合
     */
    private Map<String, Object> parseDwg(String filePath) {
        //1.打开指定工作空间
        Workspace workspace = new Workspace();
        WorkspaceConnectionInfo workspaceConnectionInfo = new WorkspaceConnectionInfo();
        workspaceConnectionInfo.setType(WorkspaceType.SMWU);
        workspaceConnectionInfo.setServer(workspacePath);
        boolean open = workspace.open(workspaceConnectionInfo);
        //打开工作空间返回值true为成功
        if (!open) {
            return AjaxResult.error("打开工作空间失败！");
        }
        //2.由工作空间打开数据源
        Datasource datasource = workspace.getDatasources().get(0);
        //3.数据源执行导入数据集
        ImportSettingDWG importSettingDwg = new ImportSettingDWG();
        importSettingDwg.setImportMode(ImportMode.OVERWRITE);
        importSettingDwg.setImportingAsCAD(true);
        importSettingDwg.setTargetDatasource(datasource);
        importSettingDwg.setSourceFilePath(filePath);
        importSettingDwg.setImportingExternalData(true);
        importSettingDwg.setImportingByLayer(true);
        DataImport dataImport = new DataImport();
        dataImport.getImportSettings().add(importSettingDwg);
        //导入数据
        ImportResult importResult = dataImport.run();
        ImportSetting[] importSettings = importResult.getFailedSettings();
        if (importSettings.length != 0) {
            return AjaxResult.error("解析失败！");
        }
        //获取所有图层名称
        String[] datasetNames = importResult.getSucceedDatasetNames(importSettingDwg);
        //机柜坐标集合
        List<GeoCabinet> geoCabinetList = new ArrayList<>();
        //文字坐标集合
        List<GeoPoint> pointList = new ArrayList<>();
        //坐标中心点/角度集合
        List<Map<Integer, EquObj>> equList = new ArrayList<>();
        //循环图层
        for (int i = 0; i < datasetNames.length; i++) {
            //获取图层名称
            String datasetName = datasetNames[i];
            DatasetVector datasetNameTemp = (DatasetVector) datasource.getDatasets().get(datasetName);
            //获取图层结果集
            Map<Integer, Feature> features = datasetNameTemp.getAllFeatures();

            JSONObject layerName = JSONUtil.createObj().put("LayerName", datasetName);
            JSONObject layerType = JSONUtil.createObj().put("type", "FeatureCollection");
            List<com.xinbochuang.machine.test.Feature> args = new ArrayList<>();

            for (Integer key : features.keySet()) {
                Geometry geometry = features.get(key).getGeometry();
                //获取数据集转GeoJson
                String result = features.get(key).FeatureSerialize(SerializeConverterType.SerializeGeojson);
                //文字类型/name图层
                if (geometry.getType().equals(GeometryType.GEOTEXT) && textLayer.equals(datasetName)) {
                    GeoText geoText = (GeoText) geometry;
                    GeoPoint point = new GeoPoint();
                    point.setName(geoText.getText());
                    point.setPoint(new Point2D.Double(geoText.getInnerPoint().x, geoText.getInnerPoint().y));
                    pointList.add(point);
                }
                //机柜图层 坐标
                if (cabinetLayer.equals(datasetName)) {

                    com.xinbochuang.machine.test.Feature arg = JSONUtil.toBean(result, com.xinbochuang.machine.test.Feature.class);
                    args.add(arg);

                    JSONObject feature = JSONUtil.parseObj(result);
                    String json = feature.get("geometry").toString();
                    if (StrUtil.isNotBlank(json) && !"null".equals(json)) {
                        JSONObject featureGeometry = JSONUtil.parseObj(json);
                        String type = featureGeometry.get("type").toString();
                        if (GEOMETRY_TYPE.equals(type)) {
                            String jsonStr=featureGeometry.get("geometries").toString();
                            System.out.println("======="+jsonStr);
                            List<JSONObject> jsonObjects = JSONUtil.toList(JSONUtil.parseArray(jsonStr), JSONObject.class);
                            if(!jsonObjects.isEmpty()){
                                JSONObject jsonObject = jsonObjects.get(0);
                                if(jsonObject.get("geometries")!=null){
                                    jsonStr=jsonObject.get("geometries").toString();
                                }
                            }
                            List<Geometries> geometriesList = JSONUtil.toList(JSONUtil.parseArray(jsonStr), Geometries.class);
                            List<Point2D.Double> points = new ArrayList<>();
                            for (Geometries geometries : geometriesList) {
                                for (Double[] coordinate : geometries.getCoordinates()) {
                                    points.add(new Point2D.Double(coordinate[0], coordinate[1]));
                                }
                            }
                            GeoCabinet geoCabinet = new GeoCabinet();
                            geoCabinet.setPoints(points);
                            geoCabinet.setEntityHandle(arg.getProperties().getEntityHandle());
                            geoCabinetList.add(geoCabinet);
                        }
                    }
                }
            }

            if (cabinetLayer.equals(datasetName)) {
                layerType.put("features", args);
                layerName.put("value", layerType);
                System.out.println("========="+JSONUtil.toJsonStr(layerName));
                Layers layers = JSONUtil.toBean(JSONUtil.toJsonStr(layerName), Layers.class);
                Map<Integer, EquObj> layerEquObj = com.xinbochuang.machine.test.GeoUtils.getLayerEquObj(layers);
                equList.add(layerEquObj);
            }

        }
        datasource.getDatasets().deleteAll();
        // 释放资源
        workspaceConnectionInfo.dispose();
        workspace.close();
        workspace.dispose();
        Map<String, Object> map = new HashMap<>();
        map.put("geoCabinetList", geoCabinetList);
        map.put("pointList", pointList);
        map.put("equList", equList);
        return map;
    }

}
